home *** CD-ROM | disk | FTP | other *** search
- /*
- * @(#)knowLocal.c 1.8 4/11/88
- */
- #include "assert.h"
- #include "nodes.h"
- #include "map.h"
- #include "sequence.h"
- #include "trace.h"
- #include "semantics.h"
- #include "builtins.h"
- #include "primitives.h"
- #include "MyParser.h"
- #include "flags.h"
-
- extern int nextLineNumber;
- static Map nodeToLocalStruct;
- extern Map manifestMap;
- static NodePtr noneNode;
-
- #define LC_makeGlobal(parent) LC_TryToAddDependent(parent, noneNode)
-
- static void LC_addDependent(parent, child)
- NodePtr parent, child;
- {
- NodePtr childStruct;
- NodePtr parentStruct;
- parentStruct = (NodePtr) Map_Lookup(nodeToLocalStruct, (int)parent);
- if ((int)parentStruct == NIL) {
- parentStruct = Construct(P_KNOWLOCAL, 3, NN, NN, NN);
- parentStruct->b.knowlocal.tag = parent->tag;
- parentStruct->b.knowlocal.definingThing = parent;
- Map_Insert(nodeToLocalStruct, (int)parent, (int)parentStruct);
- }
- childStruct = (NodePtr) Map_Lookup(nodeToLocalStruct, (int)child);
- if ((int)childStruct == NIL) {
- childStruct = Construct(P_KNOWLOCAL, 3, NN, NN, NN);
- childStruct->b.knowlocal.tag = child->tag;
- childStruct->b.knowlocal.definingThing = child;
- Map_Insert(nodeToLocalStruct, (int)child, (int)childStruct);
- }
- SET_INSERT(parentStruct->b.knowlocal.dependsOn, childStruct);
- }
-
- extern void resolveGlobal();
-
- static void LC_TryToAddDependent(parent, child)
- NodePtr parent, child;
- {
- Symbol st;
- NodePtr at;
-
- if (parent->tag == T_NONE) return;
- if (parent->tag == P_SYMDEF || parent->tag == P_SYMREF)
- parent = (NodePtr) parent->b.symref.symbol;
- if (child->tag == P_SYMDEF || child->tag == P_SYMREF)
- child = (NodePtr) child->b.symref.symbol;
- switch (parent->tag) {
- case P_SYMBOL:
- st = (Symbol) parent;
- at = GETVALUE(st->value.ATinfo);
- if (at->b.atlit.f.immutable) return;
- if (st->isManifest) {
- child = noneNode;
- } else if (st->itsKind == ST_Result || st->itsKind == ST_Param) {
- child = noneNode;
- }
- break;
- case P_INVOC:
- if (Map_Lookup(manifestMap, (int)parent) != NIL) {
- child = noneNode;
- }
- default:
- break;
- }
- switch (child->tag) {
- case P_SYMBOL:
- st = (Symbol) child;
- if (st->itsKind == ST_Result || st->itsKind == ST_Param) child = noneNode;
- LC_addDependent(parent, child);
- break;
- case P_GLOBALREF:
- resolveGlobal(child, (ValuePtr)NULL);
- assert(child->b.globalref.value != NN);
- LC_addDependent(parent, child->b.globalref.value);
- break;
- case T_NONE:
- case P_INVOC:
- case P_VECTORLIT:
- case P_BOOLLIT:
- case P_CHARLIT:
- case P_INTLIT:
- case P_REALLIT:
- case P_STRINGLIT:
- case P_BUILTINLIT:
- case P_SELFLIT:
- case P_ATLIT:
- case P_OBLIT:
- case P_NTHRESULT:
- case P_EXP:
- case P_UNARYEXP:
- LC_addDependent(parent, child);
- break;
- case P_SYMREF:
- assert(FALSE);
- break;
- default:
- LC_addDependent(parent, noneNode);
- break;
- }
- }
-
- static Map nthMap;
-
- static Boolean isSingleReferenceSymbol(), isACreation();
-
- static NodePtr getNth(p, allowSelf)
- NodePtr p;
- Boolean allowSelf;
- {
- register NodePtr nth, s = p;
- if (s->tag != P_INVOC && s->tag != P_SYMREF) return(s);
- if (s->tag == P_INVOC && isACreation(s) && allowSelf) return(s);
- if (s->tag == P_INVOC) {
- #ifdef TRYINGTGETRESULTSLOCAL
-
- This is completely garbage!
-
- s = s->b.invoc.target;
- if (s->tag != P_SYMREF || !isSingleReferenceSymbol(s)) {
- nth = (NodePtr)Map_Lookup(nthMap, (int)s);
- if (nth == (NodePtr)NIL) {
- nextLineNumber = s->lineNumber;
- nth = Construct(P_NTHRESULT, 0);
- Map_Insert(nthMap, (int)s, (int)nth);
- LC_makeGlobal(nth);
- }
- return(nth);
- }
- #else
- nth = (NodePtr)Map_Lookup(nthMap, (int)p);
- if (nth == (NodePtr)NIL) {
- nextLineNumber = p->lineNumber;
- nth = Construct(P_NTHRESULT, 0);
- Map_Insert(nthMap, (int)p, (int)nth);
- LC_makeGlobal(nth);
- }
- return(nth);
- #endif
- } else {
- assert(s->tag == P_SYMREF);
- nth = (NodePtr)Map_Lookup(nthMap, (int)s->b.symref.symbol);
- if (nth == (NodePtr)NIL) {
- nextLineNumber = s->lineNumber;
- nth = Construct(P_NTHRESULT, 0);
- Map_Insert(nthMap, (int)s->b.symref.symbol, (int)nth);
- LC_TryToAddDependent(nth, (NodePtr)s->b.symref.symbol);
- }
- return(nth);
- }
- }
-
- extern Map nodeToStruct;
- extern NodePtr findObjectOperation(), OTLookup();
-
- static NodePtr fetchCTInformation(p)
- NodePtr p;
- {
- register NodePtr ct, thing;
- register Symbol st;
- if (p->tag == P_SYMREF || p->tag == P_SYMDEF) {
- thing = (NodePtr) p->b.symdef.symbol;
- } else if (p->tag == P_SYMBOL) {
- thing = p;
- } else {
- thing = p;
- }
- ct = (NodePtr) Map_Lookup(nodeToStruct, (int) thing);
- if (ct != (NodePtr)NIL) {
- if (! ct->b.knowct.isOK) return(NULL);
- ct = GETVALUE(ct->b.knowct.answer);
- assert(ct != NULL);
- assert(ct->tag == P_OBLIT);
- } else {
- ct = NN;
- if (p->tag == P_SYMDEF || p->tag == P_SYMREF) {
- st = p->b.symdef.symbol;
- if (st->value.CTinfo != NN) ct = GETVALUE(st->value.CTinfo);
- } else if (p->tag == P_SYMBOL) {
- st = (Symbol) p;
- if (st->value.CTinfo != NN) ct = GETVALUE(st->value.CTinfo);
- }
- }
- return(ct);
- }
-
- static Boolean isACreation(p)
- register NodePtr p;
- {
- NodePtr ct, opdef;
- assert(p->tag == P_INVOC);
- ct = fetchCTInformation(p->b.invoc.target);
- if (ct == NULL) return(FALSE);
- assert(ct->tag == P_OBLIT);
- opdef = findObjectOperation(ct, p->b.invoc.opname);
- assert(opdef != NULL);
- if (! opdef->b.opdef.isInlineable) return(FALSE);
- if (opdef->b.opdef.body->b.block.stats->b.children[0]->tag != P_ASSIGNSTAT) return(FALSE);
- return(opdef->b.opdef.body->b.block.stats->b.children[0]->b.assignstat.right->b.children[0]->tag == P_OBLIT);
- }
-
- static Boolean isAConditionCreate(p)
- register NodePtr p;
- {
- NodePtr ct;
- assert(p->tag == P_INVOC);
- ct = fetchCTInformation(p->b.invoc.target);
- assert(ct != NULL);
- assert(ct->tag == P_OBLIT);
- return(ct->b.oblit.id == OIDOfBuiltin(B_IT, CONDITIONINDEX));
- }
-
- extern NodePtr getCTInfo();
-
- static Boolean isSingleReferenceSymbol(s)
- NodePtr s;
- {
- register Symbol st;
- register NodePtr ct;
- if (s->tag != P_SYMREF) return(FALSE);
- st = s->b.symref.symbol;
- if (! s->b.symref.symbol->isSingleReference) return(FALSE);
- if (s->b.symref.symbol->itsKind == ST_Param) return(FALSE);
- if (s->b.symref.symbol->itsKind == ST_Result) return(FALSE);
- ct = getCTInfo(st);
- if (ct == NULL) return(FALSE);
- assert(ct->tag == P_OBLIT);
- if (! ct->b.oblit.f.doesNotDuplicateSelf) return(FALSE);
- if (! ct->b.oblit.f.doesNotMoveArguments) return(FALSE);
- if (! ct->b.oblit.f.doesNotMoveSelf) return(FALSE);
- if (! ct->b.oblit.f.resultsDependOnlyOnArgs) return(FALSE);
- return(TRUE);
- }
-
- void buildKnowLocalGraph(p)
- register NodePtr p;
- {
- register NodePtr q, right, left, nth, nthtrue;
- register Symbol st;
- Boolean wasACreation;
-
- if ((int)p <= 0x200) return;
- switch (p->tag) {
- case P_IMPORT:
- case P_EXPORT:
- if (p->b.export.path == NN) break;
- Sequence_For(q, p->b.export.syms)
- assert(q->tag == P_SYMDEF || q->tag == P_SYMREF);
- LC_makeGlobal((NodePtr) q->b.symdef.symbol);
- Sequence_Next
- break;
- case P_ASSIGNSTAT:
- right = p->b.assignstat.right;
- left = p->b.assignstat.left;
- if (Sequence_Length(right) > 1) {
- /* is a multiple assignment */
- Sequence_For(q, left)
- assert(q->tag == P_SYMREF);
- nth = getNth(right->b.children[z__z], TRUE);
- LC_TryToAddDependent((NodePtr)q->b.symref.symbol, nth);
- LC_TryToAddDependent(nth, (NodePtr)q->b.symref.symbol);
- Sequence_Next
- } else {
- Sequence_For(q, left)
- assert(q->tag == P_SYMREF);
- nth = getNth(right->b.children[0], TRUE);
- LC_TryToAddDependent((NodePtr)q->b.symref.symbol, nth);
- LC_TryToAddDependent(nth, (NodePtr)q->b.symref.symbol);
- Sequence_Next
- }
- break;
- case P_INVOC:
- if ((q = (NodePtr) Map_Lookup(manifestMap, (int)p+2)) != (NodePtr) NIL) {
- /* a manifest invocation */
- LC_makeGlobal(p);
- break;
- }
- #ifdef JUNKKKKKKK
- if (isACreation(p)) {
- if (isAConditionCreate(p)) LC_makeGlobal(p);
- } else {
- LC_TryToAddDependent(p, getNth(p->b.invoc.target), TRUE);
- nth = getNth(p, TRUE);
- Sequence_For(q, p->b.invoc.args)
- assert(q->tag == P_ARG);
- q = q->b.arg.exp;
- if (q->tag == P_SYMREF) {
- LC_TryToAddDependent((NodePtr)q->b.symref.symbol, nth);
- } else if (q->tag == P_INVOC) {
- LC_TryToAddDependent(getNth(q, TRUE), nth);
- } else {
- LC_TryToAddDependent(q, nth);
- }
- LC_TryToAddDependent(nth, q);
- Sequence_Next
- }
- #else
- wasACreation = isACreation(p);
- if (wasACreation && isAConditionCreate(p)) {
- LC_makeGlobal(p);
- } else {
- if (!wasACreation) {
- LC_TryToAddDependent(p, getNth(p->b.invoc.target, TRUE));
- }
- nth = getNth(p, FALSE);
- nthtrue = getNth(p, TRUE);
- Sequence_For(q, p->b.invoc.args)
- assert(q->tag == P_ARG);
- q = q->b.arg.exp;
- if (q->tag == P_SYMREF) {
- LC_TryToAddDependent((NodePtr)q->b.symref.symbol, nth);
- } else if (q->tag == P_INVOC) {
- LC_TryToAddDependent(getNth(q, TRUE), nth);
- } else {
- LC_TryToAddDependent(q, nth);
- }
- if (!wasACreation) {
- LC_TryToAddDependent(nthtrue, q);
- }
- Sequence_Next
- }
- #endif
- break;
- case P_VECTORLIT:
- Sequence_For(q, p->b.vectorlit.exp)
- if (q->tag == P_SYMREF) {
- LC_TryToAddDependent((NodePtr)q->b.symref.symbol, p);
- } else if (q->tag == P_INVOC) {
- LC_TryToAddDependent(getNth(q, TRUE), p);
- } else {
- LC_TryToAddDependent(q, p);
- }
- #ifdef VECTORLITERALSDEPENDONARGS
- LC_TryToAddDependent(p, q);
- #endif
- Sequence_Next
- break;
- case P_CONSTDECL:
- st = p->b.constdecl.sym->b.symdef.symbol;
- if (st->isManifest) {
- LC_makeGlobal((NodePtr)st);
- break;
- }
- case P_VARDECL:
- st = p->b.constdecl.sym->b.symdef.symbol;
- if (p->b.constdecl.value != NN) {
- nth = getNth(p->b.constdecl.value, TRUE);
- LC_TryToAddDependent((NodePtr) st, nth);
- LC_TryToAddDependent(nth, (NodePtr) st);
- }
- break;
- case P_ATLIT:
- break;
- case P_OBLIT:
- Sequence_For(q, p->b.oblit.setq)
- if (q->b.setq.outer->tag == P_SYMREF) {
- LC_makeGlobal((NodePtr)q->b.setq.outer->b.symref.symbol);
- }
- LC_makeGlobal((NodePtr)q->b.setq.inner->b.symdef.symbol);
- Sequence_Next
- LC_TryToAddDependent(p, p->b.oblit.name);
- LC_TryToAddDependent(p->b.oblit.name, p);
- break;
- case P_VIEW:
- if (p->b.view.exp->tag == P_INVOC) {
- LC_makeGlobal(getNth(p->b.view.exp, TRUE));
- } else {
- LC_makeGlobal(p->b.view.exp);
- }
- break;
- case P_RESTRICT:
- LC_makeGlobal(p->b.restrict.exp);
- break;
- case P_MOVESTAT:
- case P_FIXSTAT:
- case P_REFIXSTAT:
- LC_makeGlobal(p->b.movestat.exp);
- break;
- case P_UNFIXSTAT:
- LC_makeGlobal(p->b.unfixstat.exp);
- break;
- default:
- break;
- }
- Sequence_For(q, p)
- if ((int)q > 0x200) buildKnowLocalGraph(q);
- Sequence_Next
- }
-
- void initializeKnowLocal()
- {
- nodeToLocalStruct = Map_Create();
- noneNode = Construct(T_NONE, 0);
- nthMap = Map_Create();
- }
-
- static char *thingName(t)
- NodePtr t;
- {
- static char buffer[128];
- if (t->b.knowlocal.tag == P_SYMBOL) sprintf(buffer, "Symbol %s (0x%08x)",
- ST_SymbolName((Symbol)(t->b.knowlocal.definingThing)), t->b.knowlocal.definingThing);
- else sprintf(buffer, "%s (0x%08x) on line %d", tagNames[(int)t->b.knowlocal.tag],
- t->b.knowlocal.definingThing, t->b.knowlocal.definingThing->lineNumber);
- return(buffer);
- }
-
- extern void findAllLocals();
-
- void displayKnowLocalGraph()
- {
- NodePtr thing, theStruct, q;
- IFTRACE(knowlocal, 5) {
- Map_For(nodeToLocalStruct, thing, theStruct)
- printf("struct 0x%08x %s", theStruct, thingName(theStruct));
- if (theStruct->b.knowlocal.isDone) {
- printf(" isDone");
- printf("%s", theStruct->b.knowlocal.isOK ? " isOK" : " isNotOK");
- }
- printf(" depends on:\n");
- Set_For(q, theStruct->b.knowlocal.dependsOn)
- printf("\t\tstruct 0x%08x %s\n", q, thingName(q));
- Set_Next
- Map_Next
- }
- }
-
- #define CODEOIDOF(p) ((p)->b.oblit.codeOID)
-
- void propagateLocalInfo(p)
- NodePtr p;
- {
- NodePtr q, aSetMember, ct = NN, newct, dt;
- Boolean isLocal = TRUE;
- register Symbol st;
-
- if (p->tag != T_SEQUENCE) p = Construct(T_SEQUENCE, 1, p);
-
- Sequence_For(aSetMember, p)
- dt = aSetMember->b.knowlocal.definingThing;
- TRACE2(knowlocal, 3, "Looking at pre-reqs of 0x%08x %s", aSetMember,
- thingName(aSetMember));
- Set_For(q, aSetMember->b.knowlocal.dependsOn)
- TRACE2(knowlocal, 4, "Looking at 0x%08x %s", q, thingName(q));
- assert(q->tag == P_KNOWLOCAL);
- if (! q->b.knowlocal.isDone) continue; /* it is in this set */
- if (!q->b.knowlocal.isOK) {
- TRACE2(knowlocal, 4, "0x%08x %s not ok, give up", q, thingName(q));
- isLocal = FALSE;
- }
- Set_Next
- if (! isLocal) break;
- assert(aSetMember->tag == P_KNOWLOCAL);
- if (dt->tag == P_OBLIT || dt->tag == P_SYMBOL) {
- newct = fetchCTInformation(dt);
- if (newct == NN) {
- TRACE2(knowlocal, 4, "0x%08x %s unknown ct, give up", aSetMember,
- thingName(aSetMember));
- isLocal = FALSE;
- } else if (ct != NN && ct != newct) {
- TRACE4(knowlocal, 4, "0x%08x %s different ct (0x%x != 0x%x), give up",
- aSetMember, thingName(aSetMember), CODEOIDOF(newct), CODEOIDOF(ct));
- isLocal = FALSE;
- } else {
- ct = newct;
- }
- }
- if (! isLocal) break;
- switch (aSetMember->b.knowlocal.tag) {
- case T_NONE:
- isLocal = FALSE;
- break;
- case P_INVOC:
- if (Map_Lookup(manifestMap, (int)dt + 1) != NIL) {
- isLocal = FALSE;
- break;
- } else {
- isLocal = TRUE;
- }
- break;
- case P_NTHRESULT: /* worried about the result */
- isLocal = TRUE;
- break;
- case P_UNARYEXP:
- case P_EXP:
- case P_BUILTINLIT:
- case P_STRINGLIT:
- case P_REALLIT:
- case P_INTLIT:
- case P_CHARLIT:
- case P_BOOLLIT:
- isLocal = FALSE;
- break;
- case P_VECTORLIT:
- /* this could be local if its target is */
- isLocal = TRUE;
- break;
- case P_SELFLIT:
- assert(FALSE);
- break;
- case P_ATLIT:
- isLocal = FALSE;
- break;
- case P_OBLIT:
- isLocal = TRUE;
- break;
- case P_SYMBOL:
- isLocal = TRUE;
- break;
- default:
- isLocal = FALSE;
- break;
- }
- if (!isLocal) break;
- Sequence_Next
- /* check that the ct is ok */
- if (isLocal && ct != NN) {
- if (! ct->b.oblit.f.doesNotDuplicateSelf) {
- TRACE1(knowlocal, 4, "ct 0%x duplicates self, give up", CODEOIDOF(ct));
- isLocal = FALSE;
- }
- if (! ct->b.oblit.f.doesNotMoveSelf) {
- TRACE1(knowlocal, 4, "ct 0%x moves self, give up", CODEOIDOF(ct));
- isLocal = FALSE;
- }
- }
- Sequence_For(aSetMember, p)
- aSetMember->b.knowlocal.isDone = TRUE;
- aSetMember->b.knowlocal.isOK = isLocal;
- aSetMember->b.knowlocal.answer = NULL;
- TRACE3(knowlocal, 1, "Finalizing 0x%08x %s: %s", aSetMember,
- thingName(aSetMember),
- aSetMember->b.knowlocal.isOK ? "is local" : "is not local");
- switch (aSetMember->b.knowlocal.tag) {
- case P_SYMBOL:
- st = (Symbol) aSetMember->b.knowlocal.definingThing;
- st->isLocal = isLocal;
- break;
- case P_OBLIT:
- aSetMember->b.knowlocal.definingThing->b.oblit.f.doLocalCreate = isLocal;
- break;
- case P_INVOC:
- aSetMember->b.knowlocal.definingThing->b.invoc.isLocal = isLocal;
- break;
- case P_NTHRESULT:
- break;
- case P_VECTORLIT:
- aSetMember->b.knowlocal.definingThing->b.vectorlit.f.doLocalCreate = isLocal;
- break;
- default:
- break;
- }
- Sequence_Next
- }
-
- static int count = 0;
- static NodePtr SCstack = NULL;
- static NodePtr SCComponent = NULL;
-
- #define min(A, B) ((A) < (B) ? (A) : (B))
-
- static void localSearchC(v)
- register NodePtr v;
- {
- register NodePtr x;
- NodePtr w;
- v->b.knowlocal.marked = TRUE;
- v->b.knowlocal.number = count++;
- v->b.knowlocal.lowLink = v->b.knowlocal.number;
- Sequence_Add(&SCstack, v);
- v->b.knowlocal.onStack = TRUE;
- Set_For(w, v->b.knowlocal.dependsOn)
- if (! w->b.knowlocal.marked) {
- localSearchC(w);
- v->b.knowlocal.lowLink = min(v->b.knowlocal.lowLink, w->b.knowlocal.lowLink);
- } else {
- if (w->b.knowlocal.number < v->b.knowlocal.number && w->b.knowlocal.onStack) {
- v->b.knowlocal.lowLink = min(w->b.knowlocal.number, v->b.knowlocal.lowLink);
- }
- }
- Set_Next
- if (v->b.knowlocal.lowLink == v->b.knowlocal.number) {
- TRACE0(knowlocal, 1, "------");
- Sequence_ReverseFor(x, SCstack)
- SCstack->nChildren --;
- assert(x->b.knowlocal.onStack);
- x->b.knowlocal.onStack = FALSE;
- if (SCComponent == NULL && x == v) {
- /* this is the only element of the component */
- SCComponent = x;
- } else {
- Sequence_Add(&SCComponent, x);
- }
- TRACE2(knowlocal, 2, "struct 0x%08x %s", x, thingName(x));
- if (x == v) break;
- Sequence_Next
- propagateLocalInfo(SCComponent);
- if (SCComponent->tag == T_SEQUENCE) {
- free((char *)SCComponent);
- }
- SCComponent = NULL;
- }
- }
-
- static void FindAllLocals()
- {
- NodePtr theThing, theStruct;
- Map_For(nodeToLocalStruct, theThing, theStruct)
- if (! theStruct->b.knowlocal.marked) localSearchC(theStruct);
- Map_Next
- }
-
- void doKnowLocals(p)
- NodePtr p;
- {
- buildKnowLocalGraph(p);
- displayKnowLocalGraph();
- FindAllLocals();
- }
-